package zdream.control.test.avatars.mm;

import org.junit.Test;
import zdream.control.foe.mm.BusterWeapon;
import zdream.control.foe.mm.IMegaManWeapon;
import zdream.control.foe.mm.MegaMan;
import zdream.control.foe.mm.MegaManBusterRestoreL2;
import zdream.control.foe.mm2pipi.MM2Pipi;
import zdream.control.foe.mm2pipi.MM2PipiEgg;
import zdream.control.foe.mm2shot.MM2ShotMan;
import zdream.control.input.SimpleWorldInput;
import zdream.control.input.WorldInput;
import zdream.control.level.LevelManagerForTest;
import zdream.control.profile.mm.MegaManProfile;
import zdream.control.region.Region;
import zdream.control.region.SimpleRegionBuilder;
import zdream.control.world.LevelWorld;
import zdream.control.world.MFoe;
import zdream.control.world.buff.HealthModule;

import static org.junit.Assert.*;
import static zdream.control.world.MFoeConstants.*;

/**
 * @author Zdream
 * @date 2024-01-09
 * @since 0.0.1
 */
public class RestoreBusterCase {
	@Test
	public void testRestoreBusterL2AttackEnemy() {
		Region region = new SimpleRegionBuilder(this.getClass().getSimpleName())
				.withRoomPositions("1")
				.withRoom(1)
						.terrain("#########################")
						.terrain("#########################")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("## S A                 ##")
						.terrain("#########################")
						.terrain("#########################")
						.terrain("#########################")
						.build()
				.withStartPoint('S')
				.defineFoe("point1", MM2ShotMan.NAME)
				.withFoeSpawnAt('A', "point1")
				.build();
		assertEquals(1, region.rooms.length);
		MegaManProfile p1 = new MegaManProfile();

		LevelManagerForTest manager = LevelManagerForTest.builder()
				.withPlayer1(p1)
				.build();
		assertEquals(LevelWorld.STATE_NONE, manager.state);
		manager.applyWorld(region);
		manager.runUntil(world -> world.state == LevelWorld.STATE_PLAYING);
		assertNotNull(manager.player1);

		MegaMan megaMan = p1.foe;
		assertNotNull(megaMan);
		assertEquals(megaMan, manager.player1);

		System.out.println("检查场地的怪");
		final MFoe enemy = manager.foes.stream()
				.filter(foe -> foe.is(MM2ShotMan.NAME))
				.findAny()
				.orElse(null);
		assertNotNull(enemy);

		System.out.printf("这里将 %s 的血量设置为一蓄力炮能打死的量%n", enemy);
		HealthModule healthModule = enemy.findOneBuff(HealthModule.CATEGORY);
		assertNotNull(healthModule);
		healthModule.hp = HP_TOKEN; // (HP = 1)

		SimpleWorldInput input = new SimpleWorldInput();
		p1.setInput(input);
		input.setDown(WorldInput.MAP_ATTACK);

		// 蓄力几秒？
		manager.runMillis(BusterWeapon.RESTORE_L2_DURATION + 500); // 超出点时间
		IMegaManWeapon weapon = megaMan.weaponModule.weapons.get(0);
		assertTrue(weapon instanceof BusterWeapon);
		assertTrue(((BusterWeapon) weapon).restoreDuration > BusterWeapon.RESTORE_L2_DURATION);

		input.setUp(WorldInput.MAP_ATTACK);
		manager.runOneFrame();

		final MFoe buster = manager.foes.stream()
				.filter(foe -> foe.is(MegaManBusterRestoreL2.NAME))
				.findAny()
				.orElse(null);
		assertNotNull(buster);

		System.out.printf("这个蓄力炮能把 %s 打掉, 并且不消失%n", enemy);
		manager.runUntil(ignored -> enemy.isDestroyed());
		assertFalse(buster.isDestroyed());

		manager.runOneFrame();
		assertFalse(manager.foes.contains(enemy));
		assertFalse(buster.isDestroyed());
	}

	@Test
	public void testRestoreBusterL2AttackMM2Pipi() {
		Region region = new SimpleRegionBuilder(this.getClass().getSimpleName())
				.withRoomPositions("1")
				.withRoom(1)
						.terrain("#########################")
						.terrain("#########################")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##                     ##")
						.terrain("##               A     ##")
						.terrain("## S                   ##")
						.terrain("#########################")
						.terrain("#########################")
						.terrain("#########################")
						.build()
				.withStartPoint('S')
				.defineFoe("point1", MM2Pipi.NAME)
				.withFoeSpawnAt('A', "point1", 0, 0)
				.build();
		assertEquals(1, region.rooms.length);
		MegaManProfile p1 = new MegaManProfile();

		LevelManagerForTest manager = LevelManagerForTest.builder()
				.withPlayer1(p1)
				.build();
		assertEquals(LevelWorld.STATE_NONE, manager.state);
		manager.applyWorld(region);
		manager.runUntil(world -> world.state == LevelWorld.STATE_PLAYING);
		assertNotNull(manager.player1);

		MegaMan megaMan = p1.foe;
		megaMan.orientation = false;
		assertNotNull(megaMan);
		assertEquals(megaMan, manager.player1);

		System.out.println("检查场地的怪");
		final MFoe pipi = manager.foes.stream()
				.filter(foe -> foe.is(MM2Pipi.NAME))
				.findAny()
				.orElse(null);
		assertNotNull(pipi);
		assertTrue(pipi instanceof MM2Pipi);
		((MM2Pipi) pipi).setVX(0); // 你别动
		final MFoe egg = manager.foes.stream()
				.filter(foe -> foe.is(MM2PipiEgg.NAME))
				.findAny()
				.orElse(null);
		assertNotNull(egg);
		pipi.orientation = false;

		manager.everyTick(ignored ->
			System.out.printf("[%4.2f] %s(%s), %s(%s), %s(%s)%n",
					manager.ticker.activeTime / 1000f,
					megaMan, megaMan.isDestroyed() ? " die " : "alive",
					pipi, pipi.isDestroyed() ? " die " : "alive",
					egg, egg.isDestroyed() ? " die " : "alive")
		);

		SimpleWorldInput input = new SimpleWorldInput();
		p1.setInput(input);
		input.setDown(WorldInput.MAP_LEFT);
		manager.runOneFrame();
		assertFalse(megaMan.orientation);

		input.setUp(WorldInput.MAP_LEFT);
		input.setDown(WorldInput.MAP_ATTACK); // 向左开枪就是不要打死鸟————至少现在憋死

		// 蓄力几秒？
		manager.runMillis(BusterWeapon.RESTORE_L2_DURATION + 500); // 超出点时间
		IMegaManWeapon weapon = megaMan.weaponModule.weapons.get(0);
		assertTrue(weapon instanceof BusterWeapon);
		assertTrue(((BusterWeapon) weapon).restoreDuration > BusterWeapon.RESTORE_L2_DURATION);

		input.setDown(WorldInput.MAP_RIGHT); // 向右看齐
		manager.runOneFrame();
		assertTrue(megaMan.orientation);

		input.setUp(WorldInput.MAP_ATTACK);
		manager.runOneFrame();
		final MFoe buster = manager.foes.stream()
				.filter(foe -> foe.is(MegaManBusterRestoreL2.NAME))
				.findAny()
				.orElse(null);
		assertNotNull(buster);
		assertTrue(buster.pos.top() > pipi.pos.bottom());
		assertTrue(buster.pos.bottom() < egg.pos.bottom());

		System.out.printf("因为 %s 的血量只有 1, 所以蓄力炮是能打死的%n", pipi);
		manager.runUntil(ignored -> pipi.isDestroyed());
		assertFalse(buster.isDestroyed());

		manager.runOneFrame();
		assertFalse(manager.foes.contains(pipi));
		assertFalse(buster.isDestroyed());
	}
}
